package zcatt.examples.swt.graphics;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.ResourceBundle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

/*
 * Derived from org.eclipse.swt.examples.
 * 
 */
public class GraphicsExample {
	static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("graphics");
	static final int MARGIN = 5;
	static final int SASH_SPACING = 1;
	static final int TIMER = 30;
	
	static boolean advanceGraphics, advanceGraphicsINit;
	
	
	Composite parent;
	GraphicsTab[] tabs;
	GraphicsTab curTab;
	GraphicsBackground curBackground;	
	
	ToolBar toolBar;
	Tree	tabTree;
	Sash	vSash;
	Canvas	canvas;
	Composite tabControlPanel;
	ToolItem backgroundItem, doubleBufferItem;
	Menu 	backgroundMenu;
	
	List<Image> imageList;		//cached to dispose
	List<GraphicsTab> tabOrderList;
	boolean isAnimated = true;
	
	
	
	
	public GraphicsExample(Composite parent)
	{
		this.parent = parent;		
		imageList = new ArrayList<>();
		createContents();
		setTab(curTab);
		startAnimationTimer();		
	}
	
	void  createContents()
	{
		//#.create graphic tabs
		tabs = new GraphicsTab[] {
				new LineTab(this),
				new BallTab(this),
				new ImageTransformImage(this),
				new TextLayoutTab(this),
				
		};		
		curTab = tabs[tabs.length -1];
		Arrays.sort(tabs, (a,b)-> a.getText().compareTo(b.getText()));
		
		//#.create toolbar
		Display display = parent.getDisplay();
		
		toolBar = new ToolBar(parent, SWT.FLAT);
		
		ToolItem back= new ToolItem(toolBar, SWT.PUSH);
		back.setText("Back");
		back.setImage(loadImage(display, "back.gif"));
		back.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int index = tabOrderList.indexOf(curTab) - 1;
				if(index < 0)
					index = tabOrderList.size() -1;
				setTab(tabOrderList.get(index));
			}			
		});
		
		ToolItem next = new ToolItem(toolBar, SWT.PUSH);
		next.setText("Next");
		next.setImage(loadImage(display, "next.gif"));
		next.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int index = tabOrderList.indexOf(curTab) + 1;
				if(index >= tabOrderList.size())
					index = 1;
				setTab(tabOrderList.get(index));
			}			
		});
		
		doubleBufferItem = new ToolItem(toolBar, SWT.CHECK);
		doubleBufferItem.setText("DoubleBuffer");
		doubleBufferItem.setImage(loadImage(display, "db.gif"));
		doubleBufferItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				setDoubleBuffer(doubleBufferItem.getSelection());
			}			
		});
		

		
		backgroundMenu = createColorMenu(parent, gb->{
			curBackground = gb;
			backgroundItem.setImage(gb.getThumbNail());
			if(canvas != null)	
				canvas.redraw();						
		});
		
		curBackground = (GraphicsBackground)backgroundMenu.getItem(0).getData();
		
		backgroundItem = new ToolItem(toolBar, SWT.PUSH);
		backgroundItem.setText("Background");
		backgroundItem.setImage(curBackground.getThumbNail());
		backgroundItem.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				assert e.widget == backgroundItem;
				Rectangle toolItemBounds = backgroundItem.getBounds();
				Point point = toolBar.toDisplay(new Point(toolItemBounds.x, toolItemBounds.y));
				backgroundMenu.setLocation(point.x, point.y + toolItemBounds.height);
				backgroundMenu.setVisible(true);				
			}			
			
		});
		
		//#.create tree
		
		tabTree = new Tree(parent, SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);

		HashSet<String> categorySet = new HashSet<>();
		for(GraphicsTab e: tabs)
		{
			categorySet.add(e.getCategory());
		}
		
		String[] categories = new String[categorySet.size()];
		categorySet.toArray(categories);
		Arrays.sort(categories);
		for(String e: categories)
		{
			TreeItem item = new TreeItem(tabTree, SWT.NONE);
			item.setText(e);
			item.setExpanded(false);
		}
		
		tabOrderList = new ArrayList<>();
		TreeItem[] items = tabTree.getItems();
		for(TreeItem item: items)
		{
			for(GraphicsTab tab: tabs)
			{
				if(item.getText().equals(tab.getCategory()))
				{
					TreeItem tabItem = new TreeItem(item, SWT.NONE);
					tabItem.setText(tab.getText());
					tabItem.setData(tab);
					tabOrderList.add(tab);
				}
			}
		}
		tabTree.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				TreeItem item = (TreeItem)e.item;
				if(item != null)
				{
					GraphicsTab tab = (GraphicsTab) item.getData();
					if(tab == curTab)
						return;
					setTab(tab);
				}
			}
			
		});
		
		//#.create vertical sash
		vSash = new Sash(parent, SWT.VERTICAL);
		
		//#.create canvas
		createCanvas();
		
		//#.create controlPanel
		Group group = new Group(parent, SWT.NONE);
		group.setText("Settings");
		tabControlPanel = group;
		tabControlPanel.setLayout(new RowLayout());
		
		//#.set layout
		FormLayout layout = new FormLayout();
		parent.setLayout(layout);
		
		FormData data;
		
		data = new FormData();
		data.left = new FormAttachment(0, MARGIN);
		data.top = new FormAttachment(0, MARGIN);
		data.right = new FormAttachment(100, -MARGIN);
		toolBar.setLayoutData(data);
		
		data = new FormData();
		data.left = new FormAttachment(0, MARGIN);
		data.top = new FormAttachment(toolBar, MARGIN);
		data.right = new FormAttachment(vSash, -SASH_SPACING);
		data.bottom = new FormAttachment(100, -MARGIN);
		tabTree.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(null, tabTree.computeSize(SWT.DEFAULT,SWT.DEFAULT).x + 50);
		data.top = new FormAttachment(toolBar, MARGIN);
		//data.right = new FormAttachment(vSash, -SASH_SPACING);
		data.bottom = new FormAttachment(100, -MARGIN);
		vSash.setLayoutData(data);
		
		data = new FormData();
		data.left = new FormAttachment(vSash, SASH_SPACING);
		data.top = new FormAttachment(toolBar, MARGIN);
		data.right = new FormAttachment(100, -MARGIN);
		data.bottom = new FormAttachment(tabControlPanel);
		canvas.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(vSash, SASH_SPACING);
		data.right = new FormAttachment(100, -MARGIN);
		data.bottom = new FormAttachment(100, -MARGIN);
		tabControlPanel.setLayoutData(data);
		
		vSash.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Rectangle rect = parent.getClientArea();
				event.x = Math.min(Math.max(event.x, 60), rect.width - 60);		//限定上下限
				if(event.detail != SWT.DRAG)
				{
					FormData data = (FormData)vSash.getLayoutData();
					data.left.offset = event.x;
					vSash.requestLayout();					
					isAnimated = true;
				}
				else
				{
					isAnimated = false;
				}
			}			
		});
	}
	
	void setTab(GraphicsTab tab)
	{
		//#.清空tabControlPanel
		Control[] children = tabControlPanel.getChildren();
		for(Control e: children)
			e.dispose();
		if(curTab != null)
			curTab.dispose();
		curTab = tab;
		
		if(curTab != null)
		{
			setDoubleBuffer(curTab.getDoubleBuffered());
			curTab.createControlPanel(tabControlPanel);
		}

		FormData data = (FormData) tabControlPanel.getLayoutData();
		if(tabControlPanel.getChildren().length != 0)
		{
			data.top = null;
		}
		else
		{
			data.top = new FormAttachment(100, -MARGIN);		//zf, 隐藏
		}
		
		parent.layout(true,true);
		
		if(curTab != null)
		{
			TreeItem[] selection = tabTree.getSelection();
			if(selection.length == 0 || selection[0].getData() != curTab)
			{
				TreeItem item = findItemByData(tabTree.getItems(), curTab);
				if(item != null)
					tabTree.setSelection(new TreeItem[] {item});
				
			}
		}
		
		canvas.redraw();
	}

	
	void startAnimationTimer()
	{
		Display display = parent.getDisplay();
		display.timerExec(TIMER, new Runnable() {

			@Override
			public void run() {
				if(canvas.isDisposed())
					return;
				int timeout = TIMER;
				if(curTab instanceof AnimatedGraphicsTab)
				{
					AnimatedGraphicsTab animTab = (AnimatedGraphicsTab) curTab;
					if(isAnimated && animTab.getAnimation())
					{
						Rectangle rect = canvas.getClientArea();
						animTab.next(rect.width, rect.height);
						canvas.redraw();
						canvas.update();
					}
					timeout = animTab.getAnimationTime();					
				}
				display.timerExec(timeout, this);
			}			
		});
	}
	
	TreeItem findItemByData(TreeItem[] items, Object data)
	{
		for(TreeItem e: items)
		{
			if(e.getData() == data)
				return e;
			e = findItemByData(e.getItems(), data);
			if(e != null)
				return e;
		}
		return null;
	}
	
	void setDoubleBuffer(boolean isDoubleBuffer)
	{
		doubleBufferItem.setSelection(isDoubleBuffer);
		recreateCanvas();		
	}
	
	void createCanvas()
	{
		int style = SWT.NO_BACKGROUND;
		if(doubleBufferItem.getSelection())
			style |= SWT.DOUBLE_BUFFERED;
		canvas = new Canvas(parent, style);
		
		canvas.addPaintListener(new PaintListener() {
			@Override
			public void paintControl(PaintEvent e) {
				GC gc = e.gc;
				Rectangle rect = canvas.getClientArea();
				Device device = gc.getDevice();
				Pattern pattern = null;
				if(curBackground.getBgColor1() != null)
				{
					if(curBackground.getBgColor2() != null)
					{
						pattern = new Pattern(device, 0,0,rect.width,rect.height,
												curBackground.getBgColor1(),
												curBackground.getBgColor2());
						gc.setBackgroundPattern(pattern);
					}
					else
					{
						gc.setBackground(curBackground.getBgColor1());
					}
				}
				else
				{
					pattern = new Pattern(device, curBackground.getBgImage());
					gc.setBackgroundPattern(pattern);
				}
				gc.fillRectangle(rect);
				if(curTab != null)
					curTab.paint(gc,  rect.width, rect.height);
				
				if(pattern != null)
					pattern.dispose();
			}			
		});		
	}
	
	void recreateCanvas()
	{
		if(canvas == null)
			return;
		if (doubleBufferItem.getSelection() == ((canvas.getStyle() & SWT.DOUBLE_BUFFERED) != 0)) 
			return;
		Object data = canvas.getLayoutData();
		canvas.dispose();
		createCanvas();
		canvas.setLayoutData(data);
		parent.layout(true, true);

	}
	

	public void dispose()
	{
		if(tabs != null)
		{
			for(GraphicsTab e : tabs)
				e.dispose();
			tabs = null;
		}
		
		if(imageList != null)
		{
			for(Image e: imageList)
				e.dispose();
			imageList = null;
		}
		
		if(backgroundMenu != null)
		{
			backgroundMenu.dispose();
			backgroundMenu = null;
		}
	}
	
	private static void addColorItems(Menu menu, ColorMenuItemListener colorMenuItemListener)
	{
		Display display = menu.getDisplay();
		if(menu.getItemCount() != 0)
			new MenuItem(menu, SWT.SEPARATOR);
		
		String[] names = new String[]{
				"White",
				"Black",
				"Red",
				"Green",
				"Blue",
				"Yellow",
				"Cyan",
			};
		
		Color[] colors = new Color[]{
				display.getSystemColor(SWT.COLOR_WHITE),
				display.getSystemColor(SWT.COLOR_BLACK),
				display.getSystemColor(SWT.COLOR_RED),
				display.getSystemColor(SWT.COLOR_GREEN),
				display.getSystemColor(SWT.COLOR_BLUE),
				display.getSystemColor(SWT.COLOR_YELLOW),
				display.getSystemColor(SWT.COLOR_CYAN),
			};

		for (int i = 0; i < names.length; i++) {
			MenuItem item = new MenuItem(menu, SWT.NONE);
			item.setText(names[i]);
			item.addSelectionListener(colorMenuItemListener);			//selection listener
			Color color = colors[i];
			GraphicsBackground gb = new GraphicsBackground();
			Image image = GraphicsExample.createColorImage(display, color);
			gb.setBgColor1(color);
			gb.setBgImage(image);
			gb.setThumbNail(image);
			colorMenuItemListener.imageList.add(image);
			item.setImage(image);
			item.setData(gb);
		}
		
		colorMenuItemListener.customColorMI = new MenuItem(menu, SWT.NONE);
		colorMenuItemListener.customColorMI.setText("CustomColor");
		colorMenuItemListener.customColorMI.addSelectionListener(colorMenuItemListener);
		GraphicsBackground gb = new GraphicsBackground();
		colorMenuItemListener.customColorMI.setData(gb);
	}
	
	private static void addPatternItems(Menu menu, ColorMenuItemListener colorMenuItemListener)
	{
		Display display = menu.getDisplay();

		if (menu.getItemCount() != 0) {
			new MenuItem(menu, SWT.SEPARATOR);
		}

		// pattern names
		String[] names = new String[]{
			"Pattern1",
			"Pattern2",
			"Pattern3",
		};

		// pattern images
		Image[] images = new Image[]{
			loadImage(display, "pattern1.jpg"),
			loadImage(display, "pattern2.jpg"),
			loadImage(display, "pattern3.jpg"),
		};
		colorMenuItemListener.imageList.add(images[0]);
		colorMenuItemListener.imageList.add(images[1]);
		colorMenuItemListener.imageList.add(images[2]);

		for (int i = 0; i < names.length; i++) {
			MenuItem item = new MenuItem(menu, SWT.NONE);
			item.setText(names[i]);
			item.addSelectionListener(colorMenuItemListener);
			Image image = images[i];
			GraphicsBackground gb = new GraphicsBackground();
			gb.setBgImage(image);
			gb.setThumbNail(image);
			item.setImage(image);
			item.setData(gb);
		}

		// add the custom pattern item
		colorMenuItemListener.customPatternMI = new MenuItem(menu, SWT.NONE);
		colorMenuItemListener.customPatternMI.setText("CustomPattern"); 
		colorMenuItemListener.customPatternMI.addSelectionListener(colorMenuItemListener);
		GraphicsBackground gb = new GraphicsBackground();
		colorMenuItemListener.customPatternMI.setData(gb);
	}
	private static void addGradientItems(Menu menu, ColorMenuItemListener colorMenuItemListener)
	{
		if (menu.getItemCount() != 0) {
			new MenuItem(menu, SWT.SEPARATOR);
		}
		colorMenuItemListener.customGradientMI = new MenuItem(menu, SWT.NONE);
		colorMenuItemListener.customGradientMI.setText("Gradient");
		colorMenuItemListener.customGradientMI.addSelectionListener(colorMenuItemListener);
		GraphicsBackground gb = new GraphicsBackground();
		colorMenuItemListener.customGradientMI.setData(gb);
	}
	
	public static Menu createColorMenu(Control control, ColorListener colorListener)
	{
		Menu menu = new Menu(control);
		ColorMenuItemListener menuItemListener = new ColorMenuItemListener(control, colorListener);
		menu.addDisposeListener(menuItemListener);
		
		addColorItems(menu, menuItemListener);		
		addPatternItems(menu, menuItemListener);		
		addGradientItems(menu, menuItemListener);				
	
		return menu;
	}
	
	public static Image loadImage(Device device, String imageName)
	{
		InputStream is = GraphicsExample.class.getResourceAsStream(imageName);
		if(is == null)
			return null;
		Image res = null;
		try {
			res = new Image(device, is);
		}
		catch(Exception e)
		{}
		finally
		{
			try {
				is.close();
			}
			catch(Exception e)
			{}
		}
		return res;
	}
	
	public static String getResourceString(String key)
	{
		try {
			return RESOURCE_BUNDLE.getString(key);
		}
		catch(Exception e)
		{
			assert false;
			return key;
		}
	}
	
	public static Image createThumbnail(Device device, String fileName)
	{
		Image image = new Image(device, fileName);
		Rectangle src = image.getBounds();
		Image result = null;
		if (src.width != 16 || src.height != 16) {
			result = new Image(device, 16, 16);
			GC gc = new GC(result);
			Rectangle dest = result.getBounds();
			gc.drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height);
			gc.dispose();
		}
		if (result != null) {
			image.dispose();
			return result;
		}
		return image;
	}

	public static Image createColorImage(Device device, Color color)
	{
		Image image = new Image(device, 16, 16);
		GC gc = new GC(image);
		gc.setBackground(color);
		Rectangle rect = image.getBounds();
		gc.fillRectangle(rect);
		if (color.equals(device.getSystemColor(SWT.COLOR_BLACK))) {
			gc.setForeground(device.getSystemColor(SWT.COLOR_WHITE));
		}
		//gc.drawRectangle(rect.x, rect.y, rect.width - 1, rect.height - 1);
		gc.dispose();
		return image;
	}

	public static Image createColorImage(Device device, Color color1, Color color2, int width, int height) {
		Image image = new Image(device, width, height);
		GC gc = new GC(image);
		Rectangle rect = image.getBounds();
		Pattern pattern = new Pattern(device, rect.x, rect.y, rect.width-1, rect.height -1,
									color1, color2);
		gc.setBackgroundPattern(pattern);
		gc.fillRectangle(rect);
		//gc.drawRectangle(rect.x, rect.y, rect.width -1, rect.height -1);
		gc.dispose();
		pattern.dispose();
		
		return image;
	}
	
	static class ColorMenuItemListener implements SelectionListener, DisposeListener
	{
		MenuItem customColorMI, customPatternMI, customGradientMI;	// custom menu items

		Control parent;
		List<Image> imageList;
		
		Image customImage, customImageThumb;
		Color customColor;
		GraphicsBackground background;	//上次的background信息
		ColorListener colorListener;
		
		public ColorMenuItemListener(Control parent, ColorListener colorListener)
		{
			this.parent = parent;
			this.colorListener = colorListener;
			
			imageList = new ArrayList<>();
		}
		

		@Override
		public void widgetDisposed(DisposeEvent event) {
			for(Image e: imageList)
				e.dispose();
			//imageList = null;			
			imageList = new ArrayList<>();			
		}

		@Override
		public void widgetSelected(SelectionEvent event) {
			Display display = parent.getDisplay();
			MenuItem item = (MenuItem) event.widget;
			if(item == customColorMI)
			{
				ColorDialog clrDialog = new ColorDialog(parent.getShell());
				if(customColor != null && !customColor.isDisposed())
				{
					clrDialog.setRGB(customColor.getRGB());
				}
				RGB rgb = clrDialog.open();
				if(rgb == null) return;
				customColor = new Color(rgb);
				
				if(customPatternMI != null)	customPatternMI.setImage(null);
				if(customGradientMI != null)	customGradientMI.setImage(null);
				
				if(customImage != null)	customImage.dispose();
				if(customImageThumb != null)	customImageThumb.dispose();
				
				customImage = createColorImage(display, customColor);
				customImageThumb = createColorImage(display, customColor);
				
				GraphicsBackground gb = new GraphicsBackground();
				gb.setBgImage(customImage);
				gb.setThumbNail(customImageThumb);
				gb.setBgColor1(customColor);
				item.setData(gb);
				item.setImage(customImage);
				imageList.add(customImage);
				imageList.add(customImageThumb);
			}
			else if (item == customPatternMI)
			{
				FileDialog dialog = new FileDialog(parent.getShell());
				dialog.setFilterExtensions(new String[] {"*.jpg", "*.gif", "*.*"});
				String fileName = dialog.open();
				if(fileName == null)	return;
				
				if(customPatternMI != null)	customPatternMI.setImage(null);
				if(customGradientMI != null)	customGradientMI.setImage(null);
				
				if(customImage != null)	customImage.dispose();
				if(customImageThumb != null)	customImageThumb.dispose();

				customImage = new Image(display, fileName);
				customImageThumb = createThumbnail(display, fileName);
				
				GraphicsBackground gb = new GraphicsBackground();
				gb.setBgImage(customImage);
				gb.setThumbNail(customImageThumb);
				item.setData(gb);
				item.setImage(customImage);
				imageList.add(customImage);
				imageList.add(customImageThumb);			
			}
			else if (item == customGradientMI)
			{
				GradientDialog dialog = new GradientDialog(parent.getShell());
				if(background != null)
				{
					if (background.getBgColor1() != null)
						dialog.setFirstRGB(background.getBgColor1().getRGB());
					if (background.getBgColor2() != null)
						dialog.setSecondRGB(background.getBgColor2().getRGB());					
				}
				if(dialog.open() != SWT.OK)	return;
				
				Color colorA = new Color(dialog.getFirstRGB());
				Color colorB = new Color(dialog.getSecondRGB());
				if (colorA == null || colorB == null) return;

				if(customColorMI != null)	customColorMI.setImage(null);
				if(customPatternMI != null)	customPatternMI.setImage(null);
				
				if(customImage != null)	customImage.dispose();
				if(customImageThumb != null)	customImageThumb.dispose();
				
				customImage = createColorImage(display, colorA, colorB, 16, 16);
				customImageThumb = createColorImage(display, colorA, colorB, 16, 16);
				
				GraphicsBackground gb = new GraphicsBackground();
				gb.setBgImage(customImage);
				gb.setThumbNail(customImageThumb);
				gb.setBgColor1(colorA);
				gb.setBgColor2(colorB);
				item.setData(gb);
				item.setImage(customImage);
				imageList.add(customImage);
				imageList.add(customImageThumb);				
			}
			else
			{
				if(customColorMI != null)	customColorMI.setImage(null);
				if(customPatternMI != null)	customPatternMI.setImage(null);
				if(customGradientMI != null)	customGradientMI.setImage(null);				
			}
			
			background = (GraphicsBackground) item.getData();
			colorListener.setColor(background);
		}		

		@Override
		public void widgetDefaultSelected(SelectionEvent event) {			
		}		
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText(getResourceString("GraphicsExample"));
		new GraphicsExample(shell);		
		shell.open();
		while(!shell.isDisposed())
		{
			if(!display.readAndDispatch())
				display.sleep();
		}
		shell.dispose();
	}
}
